package cn.jtool.dig.server.comm;

import cn.jtool.dig.common.netty.TcpServer;
import cn.jtool.dig.server.comm.real.RealChannelInitializer;
import cn.jtool.dig.server.comm.tunnel.TunnelChannelInitializer;
import cn.jtool.dig.server.configuration.TunnelProperties;
import cn.jtool.dig.server.domain.response.PortMappingDetailResponse;
import cn.jtool.dig.server.domain.response.PortMappingListResposne;
import cn.jtool.dig.server.service.PortMappingService;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class ServerManager implements CommandLineRunner {

    private final Map<String, TcpServer> serverMap = Maps.newConcurrentMap();
    @Resource
    private TunnelProperties tunnelProperties;
    @Resource
    private PortMappingService portMappingService;
    @Resource
    private RealChannelInitializer realChannelInitializer;
    @Resource
    private TunnelChannelInitializer tunnelChannelInitializer;

    @Override
    public void run(String... args) throws Exception {
        this.startTunnelServer();
        this.startRealServer();
    }

    private void startTunnelServer(){
        TcpServer tcpServer = new TcpServer("tunnelServer", tunnelProperties.getServerIp(), tunnelProperties.getServerPort(), this.tunnelChannelInitializer);
        tcpServer.start();
        this.serverMap.put("tunnelServer", tcpServer);
    }

    private void startRealServer(){
        List<PortMappingListResposne> tunnelListResponse = this.portMappingService.list(null);
        if(CollectionUtils.isNotEmpty(tunnelListResponse)){
            tunnelListResponse.forEach(portMappingListResposne -> {
                this.startTunnel(this.portMappingService.selectOne(portMappingListResposne.getId()));
            });
        }
    }

    public void stopTunnel(PortMappingDetailResponse tunnel){
        TcpServer tcpServer = this.serverMap.get(tunnel.getPortMappingName());
        tcpServer.stop();
        this.serverMap.remove(tunnel.getPortMappingName());
    }

    public void startTunnel(PortMappingDetailResponse tunnel){
        if(tunnel.getEnableState() == 1) {
            TcpServer tcpServer = new TcpServer(tunnel.getPortMappingName(), "0.0.0.0", tunnel.getSourcePort(), this.realChannelInitializer);
            tcpServer.start();
            this.serverMap.put(tunnel.getPortMappingName(), tcpServer);
        }else{
            log.warn("隧道 {} 被禁用", tunnel.getPortMappingName());
        }
    }

}
